/*+*********************************************************
Filename: B01_dual_mic\src\top.v
Description:
  capture data from two mics, simple process and send to dac.

Modification:
2024.04.05 creation by H.Zheng
**********************************************************-*/

module top(
	input wire clk,
	input wire rst_n,
	input wire uart_rx,
	output wire uart_tx,
  output wire [5:0] led, 

  output wire mic_ws,
  output wire mic_ck,
  output wire mic_lr,
  input wire mic_data,
  output wire mic2_ws,
  output wire mic2_ck,
  output wire mic2_lr,
  input wire mic2_data,

  output wire dac_ws,
  output wire dac_bck,
  output wire dac_data,
  output wire dac_pa_en

);




//assign led = 6'b111001;


/**
 * clock section
 */
wire clk1m;
wire clk6m;
PLL_6M PLL6m(
    .clkout(clk6m),
    .clkoutd(clk1m),
    .clkin(clk)
);


/**
 * uart section
 */
parameter                        CLK_FRE  = 27;//Mhz
parameter                        UART_FRE = 500000;//hz
wire[7:0]                         tx_data;
wire                              tx_data_valid;
wire                             tx_data_ready;

uart_tx#
(
	.CLK_FRE(CLK_FRE),
	.BAUD_RATE(UART_FRE)
) uart_tx_inst
(
	.clk                        (clk                      ),
	.rst_n                      (rst_n                    ),
	.tx_data                    (tx_data                  ),
	.tx_data_valid              (tx_data_valid            ),
	.tx_data_ready              (tx_data_ready            ),
	.tx_pin                     (uart_tx                  )
);

/**
 * mic section
 */
assign mic_lr = 1'b0;
assign mic2_lr = 1'b0;

reg [7:0] mic_counter;

always @(posedge clk6m or negedge rst_n) begin
    if (!rst_n)
        mic_counter <= 8'd0;
    else
        mic_counter <= mic_counter + 1'd1;
end

wire clk_3072kHz_n = mic_counter[0];  //6/2
wire clk_48kHz_n   = mic_counter[6]; //3/64=6/128

assign mic_ck = clk_3072kHz_n;
assign mic_ws = clk_48kHz_n;
assign mic2_ck = clk_3072kHz_n;
assign mic2_ws = clk_48kHz_n;


/**
 * receive mic data
 */
reg [63:0] shift_reg;

always @(posedge mic_ck) begin
    shift_reg <= {shift_reg[62:0], mic_data};	
end	
    
reg [63:0] data_reg;
always  @(negedge mic_ws) begin
    data_reg <= shift_reg;
end		

wire[23:0] data_l = data_reg[62:39];	
wire[23:0] data_r = data_reg[30:7];	    

//assume that it's signed data    
wire[22:0] l_amplitude = data_l[23] ? ((~data_l[22:0])+1'b1) : data_l[22:0];
wire loud_voice = (l_amplitude[22:16]>=7'h07) ? 1'b1 : 1'b0;    




/**
 * receive mic2 data
 */
reg [63:0] shift_reg2;

always @(posedge mic_ck) begin
    shift_reg2 <= {shift_reg2[62:0], mic2_data};	
end	
    
reg [63:0] data_reg2;
always  @(negedge mic_ws) begin
    data_reg2 <= shift_reg2;
end		

wire[23:0] data_l2 = data_reg2[62:39];	
wire[23:0] data_r2 = data_reg2[30:7];	    

wire[22:0] l_amplitude2 = data_l2[23] ? ((~data_l2[22:0])+1'b1) : data_l2[22:0];
wire loud_voice2 = (l_amplitude2[22:16]>=7'h07) ? 1'b1 : 1'b0;    

/**
 * data process
 */
//delay data from mic for 8 sample clk and sum with data from mic2

reg [23:0] delayed_data[0:7];
always  @(negedge mic_ws) begin
    delayed_data[0] <= data_l;
    delayed_data[1] <= delayed_data[0];
    delayed_data[2] <= delayed_data[1];
    delayed_data[3] <= delayed_data[2];
    delayed_data[4] <= delayed_data[3];
    delayed_data[5] <= delayed_data[4];
    delayed_data[6] <= delayed_data[5];
    delayed_data[7] <= delayed_data[6];
end		 

wire [24:0] summed_data;
assign summed_data = {delayed_data[5][23], delayed_data[5]} + {data_l2[23], data_l2};

wire overflow_flag = (~summed_data[24])&(summed_data[23]);
wire underflow_flag = (summed_data[24])&(~summed_data[23]);

wire [23:0] result_data = overflow_flag ? 24'h7ff :
                          underflow_flag ? 24'h800 : summed_data[23:0];


//uart tx data and trigger signal
assign tx_data = result_data[23:16];
reg [1:0] mic_ws_edge;
always @(negedge clk) begin
    mic_ws_edge <= {mic_ws_edge[0], mic_ws};	
end
assign tx_data_valid = (~mic_ws_edge[1]) & mic_ws_edge[0]; //posedge of mic_ws trigger a uart tx


/**
 * DAC interface
 */

assign dac_bck = mic_counter[1]; //32 bck per ws period

dac_pt8211 pt8211_u1(
    .data_in_clk(tx_data_valid),
//    .data_r(data_r[23:8]),
    .data_r(result_data[23:8]),
    .data_l(data_l2[23:8]),
    .dac_if_bck(dac_bck),
    .dac_if_ws(dac_ws),
    .dac_if_data(dac_data)
);

assign dac_pa_en = 1'b1;




/**
 * led
 */
assign led = {~loud_voice2, 4'b1111 , ~loud_voice};
//assign led = ~l_amplitude[22:17];

endmodule